
#include <stdio.h>
#include <string.h>
#include <stdarg.h>


#include "Utils.h"
#include "logfile.h"
#include "OSMutex.h"



LogFile::LogFile():m_pFile(NULL), m_nLength(0)
{
    memset(m_strFileName, 0, sizeof(m_strFileName));
}

//close the previous file, and open the file 'pFilePath'. 
bool LogFile::Open(char * pFilePath)
{
    if(pFilePath == NULL || strlen(pFilePath) >= sizeof(m_strFileName))
        return false;

    if(NULL != m_pFile)
        fclose(m_pFile);

    m_pFile = fopen(pFilePath, "w+");
    m_nLength = 0;
    if(NULL == m_pFile)
    {
        printf("%s(%d): Cannot open log file: %s\r\n", __FILE__, __LINE__, pFilePath);
        return false;
    }
    printf("log file(%s) is opended.\r\n", pFilePath);
    strcpy(m_strFileName, pFilePath);
    return true;
}

int LogFile::Write(const char *buf,int len)
{
    if(NULL == m_pFile)return -1;

    int ret = fwrite(buf, 1, len, m_pFile);
    if(ret <= 0) return ret;
    fflush(m_pFile);

    m_nLength += len;
    return len;
}
void LogFile::Close()
{
    if (NULL != m_pFile)
    {
        fclose(m_pFile);
        m_pFile = NULL;
    }
}

LogFileManager::LogFileManager(): m_bIsInitailized(false), m_nCurrentIndex(0),m_LogFile(),m_LogOutDev(LOG_OUT_CONSOLE),m_LogMutex()
{
    memset(m_strLogDir, 0, sizeof(m_strLogDir));
    memset(m_strLogBuffer, 0, sizeof(m_strLogBuffer));
}

bool LogFileManager::Initialize(const char *pDir, LOG_OUT_DEV outDev )
{
    if(m_bIsInitailized)return true;
    
    int len = strlen(pDir);
    if(NULL == pDir || len >= (int)sizeof(m_strLogDir) - 2)
    {
    	  printf("%s(%d) failed\r\n", __FUNCTION__, __LINE__);
        return false;
    }
    m_bIsInitailized = true;
    m_LogOutDev = outDev;

    if (outDev == LOG_OUT_FILE)
    {
        strcpy(m_strLogDir, pDir);
        if (pDir[len - 1] != '\\' && pDir[len - 1] != '/')
        {
            m_strLogDir[len] = kPathDelimiterChar;
            m_strLogDir[len + 1] = '\0';
        }
        OpenNewLogFile();
    }
    return true;
}
bool LogFileManager::OpenNewLogFile()
{
    m_nCurrentIndex ++;
    if (m_nCurrentIndex > MAX_LOG_FILE)
    {
        m_nCurrentIndex = 1;
    }

#ifdef __Win32__
	char szTime[32] = { 0 };
	Utils::GetNameTime(szTime, 32);

    char filepath[512] = "";
	sprintf(filepath, "%slog_%d_%s.txt", m_strLogDir, m_nCurrentIndex, szTime );
#else
	char filepath[512] = "";
	sprintf(filepath, "%slog_%d.txt", m_strLogDir, m_nCurrentIndex);
#endif
    return m_LogFile.Open(filepath);
}

//int LogFileManager::WriteLog(char *filePath, int line, char *fmt, ...)
int LogFileManager::WriteLog(const char *pfunc, int line, const char *fmt, va_list va)
{
    OSMutexLocker locker(&m_LogMutex);

    char *pStartPos = m_strLogBuffer;
    //const char* pFileName = GetFilename(filePath);
    int len = sizeof(m_strLogBuffer) - 1;
#if 0
    pStartPos +=  OS::Time2Str(pStartPos, len);
#else
    //time_t theTime = OS::UnixTime_Secs();
    //struct tm *current = localtime(&theTime);
    //pStartPos +=  sprintf(pStartPos, "%d-%d:%d:%d", current->tm_mday, current->tm_hour, current->tm_min,current->tm_sec);
#endif
    //pStartPos += sprintf(pStartPos, "-%s(%d): ", pFileName, line);

	if (NULL != pfunc)
	{
		pStartPos += sprintf(pStartPos, "%s(%d): ", pfunc, line);
		len -= (pStartPos - m_strLogBuffer);
	}

    char *p = pStartPos;
    int ret = 0;
    //va_list		va;

    //va_start(va, fmt);
#ifdef __Win32__
    ret += _vsnprintf(p, len, fmt, va);
#else
    ret += vsnprintf(p, len, fmt, va);
#endif
    //va_end(va);

    if( LOG_OUT_FILE == m_LogOutDev)
    {
        ret = m_LogFile.Write(m_strLogBuffer, (pStartPos - m_strLogBuffer) + ret);
        if(m_LogFile.GetLength() >= LOG_FILE_SIZE)
        {
            OpenNewLogFile();
        }
    }
    else
    {
        ret += (pStartPos - m_strLogBuffer);
        printf(m_strLogBuffer);
    }
    return ret;
}

const char* LogFileManager::GetFilename(char* filePath)
{
    char *p;

    p = filePath;
    while (*p != '\0')
    {	
        p++;
    }

    while (p != filePath) 
    {
        if (*p == kPathDelimiterChar)
            break;
        p--;
    }

    if (p != filePath) 
    {
        /* '\\' exist */
        p++;
    }

    return p;
}

static LogFileManager m_LogManager;

// Add by caoyanming 20170815 Start
static HeartBeatLogFileManager m_HeartbeatLogManager;
// Add by caoyanming 20170815 End

extern "C" int log_write(const char *pfunc, int line, const char *fmt, ...)
{
    int ret = 0;
    va_list va;
    va_start(va, fmt);
    ret = m_LogManager.WriteLog(pfunc, line, fmt, va);
    va_end(va);
    return ret;
}

extern "C" int log_tracehex(const char *fmt, ...)
{
	int ret = 0;
	va_list va;
	va_start(va, fmt);
	ret = m_LogManager.WriteLog(NULL, 0, fmt, va);
	va_end(va);
	return ret;
}


extern "C" void log_initialize(const char *pDir, LOG_OUT_DEV outDev)
{
    m_LogManager.Initialize(pDir, outDev);
}

// Add by caoyanming 20170815 Start
extern "C" void log_heartbeat_initialize(const char *pDir, LOG_OUT_DEV outDev)
{
	m_HeartbeatLogManager.Initialize(pDir, outDev);
}
extern "C" int log_heartbeat_write(const char *pfunc, int line, const char *fmt, ...)
{
	int ret = 0;
	va_list va;
	va_start(va, fmt);
	ret = m_HeartbeatLogManager.WriteLog(pfunc, line, fmt, va);
	va_end(va);
	return ret;
}

int HeartBeatLogFileManager::WriteLog(const char *pfunc, int line, const char *fmt, va_list va)
{
	OSMutexLocker locker(&m_LogMutex);

	char *pStartPos = m_strLogBuffer;
	//const char* pFileName = GetFilename(filePath);
	int len = sizeof(m_strLogBuffer) - 1;
#if 0
	pStartPos += OS::Time2Str(pStartPos, len);
#else
	//time_t theTime = OS::UnixTime_Secs();
	//struct tm *current = localtime(&theTime);
	//pStartPos +=  sprintf(pStartPos, "%d-%d:%d:%d", current->tm_mday, current->tm_hour, current->tm_min,current->tm_sec);
#endif
	//pStartPos += sprintf(pStartPos, "-%s(%d): ", pFileName, line);

	if (NULL != pfunc)
	{
		pStartPos += sprintf(pStartPos, "%s(%d): ", pfunc, line);
		len -= (pStartPos - m_strLogBuffer);
	}

	char *p = pStartPos;
	int ret = 0;
	//va_list		va;

	//va_start(va, fmt);
#ifdef __Win32__
	ret += _vsnprintf(p, len, fmt, va);
#else
	ret += vsnprintf(p, len, fmt, va);
#endif
	//va_end(va);

	if (LOG_OUT_FILE == m_LogOutDev)
	{
		ret = m_LogFile.Write(m_strLogBuffer, (pStartPos - m_strLogBuffer) + ret);
		if (m_LogFile.GetLength() >= LOG_HEARTBEAT_FILE_SIZE)
		{
			OpenNewLogFile();
		}
	}
	else
	{
		ret += (pStartPos - m_strLogBuffer);
		printf(m_strLogBuffer);
	}
	return ret;
}
// Add by caoyanming 20170815 End

//extern "C" void log_initialize(const char *pDir, const char* psOutDev)
//{
//    LOG_OUT_DEV outDev = LOG_OUT_CONSOLE;
//    if (strcmp(psOutDev, "file"))
//        outDev = LOG_OUT_FILE;
//    else if(strcmp(psOutDev, "net"))
//        outDev = LOG_OUT_NET;
//    m_LogManager.Initialize(pDir, outDev);
//}